/**
 *    Copyright 2010 Merrick Zhang ( anphorea@gmail.com )
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */
package anpho.proxyvalidator.provider;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Get Proxy List from www.cnproxy.com
 * 
 * @author Merrick
 * @version 2010.07.02
 */
public class Cnproxy extends AProxyProvider {

	Logger log = LoggerFactory.getLogger(this.getClass());

	// these strings are used to replace the cipher text.
	final static String z = "3";
	final static String m = "4";
	final static String k = "2";
	final static String l = "9";
	final static String d = "0";
	final static String x = "5";
	final static String i = "7";
	final static String w = "6";
	final static String q = "8";
	final static String b = "1";

	// URLs of Cnproxy website.
	final static String[] urls = { "http://www.cnproxy.com/proxy1.html",
			"http://www.cnproxy.com/proxy2.html",
			"http://www.cnproxy.com/proxy3.html",
			"http://www.cnproxy.com/proxy4.html",
			"http://www.cnproxy.com/proxy5.html",
			"http://www.cnproxy.com/proxy6.html",
			"http://www.cnproxy.com/proxy7.html",
			"http://www.cnproxy.com/proxy8.html",
			"http://www.cnproxy.com/proxy9.html",
			"http://www.cnproxy.com/proxy10.html",
			"http://www.cnproxy.com/proxyedu1.html",
			"http://www.cnproxy.com/proxyedu2.html" };

	final static String REP_STR = "<SCRIPT type=text/javascript>document\\.write\\(\":\"";

	// (x.x.x.x):(x) pattern,used to extract IP and port data from the web page.
	final static Pattern regexpForIp_Port = Pattern
			.compile("(\\d+\\.\\d+\\.\\d+\\.\\d+):(\\d+)");

	/*
	 * (non-Javadoc)
	 * 
	 * @see anpho.proxyvalidator.provider.AProxyProvider#getProxies()
	 */
	@Override
	public Set<Proxy> getProxies() {
		Set<Proxy> allProxies = new HashSet<Proxy>();
		for (String u : urls) {
			allProxies.addAll(process(u));
		}
		log.info("Extracted {} Proxies In Total.", allProxies.size());
		return allProxies;
	}

	/**
	 * process the URL and return the extracted Proxy list.
	 * 
	 * @param url
	 * @return
	 */
	Set<Proxy> process(String url) {
		Set<Proxy> result = new HashSet<Proxy>();

		String content = "";
		try {
			content = getFileAsString(url);
		} catch (IOException e) {
			log.error(e.getMessage());
		}
		content = content.replaceAll(REP_STR, ":");
		content = content.replaceAll("\\+", "");
		content = content.replaceAll("z", z);
		content = content.replaceAll("m", m);
		content = content.replaceAll("k", k);
		content = content.replaceAll("l", l);
		content = content.replaceAll("d", d);
		content = content.replaceAll("x", x);
		content = content.replaceAll("i", i);
		content = content.replaceAll("w", w);
		content = content.replaceAll("q", q);
		content = content.replaceAll("b", b);

		// search for x.x.x.x:x pattern
		Matcher matcher = regexpForIp_Port.matcher(content);

		while (matcher.find()) {
			try {
				Proxy p = new Proxy(Type.HTTP, new InetSocketAddress(matcher
						.group(1), Integer.parseInt(matcher.group(2))));
				result.add(p);
				log.info("Found Proxy : {}", p.toString());
			} catch (IllegalArgumentException e) {
				log.error(e.getMessage());
			}
		}

		log.debug("Extracted {} Proxies From URL {}", result.size(), url);
		return result;
	}
}
